package com.powernode.service.impl;

import cn.hutool.core.util.StrUtil;
import com.powernode.constant.AuthConstant;
import com.powernode.domain.LoginUser;
import com.powernode.mapper.LoginUserMapper;
import com.powernode.mapper.SysLoginUserMapper;
import com.powernode.service.factory.LoginServiceFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;


/**
 * @author syo 2319615164@qq.com
 * @description 用户详情服务实现
 * @date 2024/3/31
 * @Copyright syo
 */
@Service
@RequiredArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {

    private final SysLoginUserMapper sysLoginUserMapper;

    private final LoginUserMapper loginUserMapper;

    private final RestTemplate restTemplate;

    private final LoginServiceFactory loginServiceFactory;

    @Value("${wx.appid}")
    private String appid;

    @Value("${wx.secret}")
    private String secret;

    @Value("${wx.url}")
    private String url;

    /**
     * 根据用户名查询数据库的方法（因为我们有2个前端，所以要区分开来）
     * @param username      用户名
     * @return  UserDetails 用于框架认证授权的
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 1. 获取request请求对象
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        // 1.1 获取request请求对象
        assert requestAttributes != null;
        HttpServletRequest request = requestAttributes.getRequest();

        // 2. 获取请求头中的用户类型（后台管理员or会员）
        String loginType = request.getHeader(AuthConstant.LOGIN_TYPE);

        // 3. 判断登录类型是否为空
        if (StrUtil.isEmpty(loginType)) {
            return null;
        }

        // 4. 登录逻辑
        return loginServiceFactory.getLoginService(loginType).realLogin(username);

        /*
        // 4. 判断用户类型
        switch (loginType) {
            case AuthConstant.SYS_USER:
                // 4.1 后台管理员用户
                // 4.2 根据用户名查询用户
                SysLoginUser sysLoginUser = sysLoginUserMapper.selectOne(new LambdaQueryWrapper<SysLoginUser>()
                        .eq(SysLoginUser::getUsername, username)
                );
                // 4.3 判断用户是否存在
                if (ObjectUtil.isNotNull(sysLoginUser)) {
                    // 4.4 后台管理员有权限，查询当前登录管理员的权限
                    List<String> auths = sysLoginUserMapper.selectAuthsByUserId(sysLoginUser.getUserId());
                    if (CollectionUtil.isNotEmpty(auths) && auths.size() != 0) {
                        // 4.5 将查询出来的权限封装到用户对象中
                        sysLoginUser.setAuths(auths);
                    }
                }
                return sysLoginUser;

                // 4.6 如果是微信小程序端
            case AuthConstant.MEMBER:

                // 调用微信登录凭证校验接口来获取用户唯一标识用户OpenID
                //  String url = "https://api.weixin.qq.com/sns/jscode2session?" +
                // "appid="+ appid +"secret="+ secret +"js_code="+ js_code +"grant_type=authorization_code";

                final String URL = String.format(url, appid, secret, username);

                // 调用接口响应json字符串
                String resultJSONStr = restTemplate.getForObject(URL, String.class);

                // 解析json
                JSON json = JSONUtil.parse(resultJSONStr);
                // 获取唯一标识openid
                String openid = json.getByPath("openid", String.class);
                // 如果没有值
                if (StrUtil.isEmpty(openid)) {
                    return null;
                }
                // 如果有值则应该去建立自己系统的用户体系
                // 我们需要根据微信openid判断用户是否存在于我们的用户体系内
                // 如果存在则直接登录，如果不存在创建用户并登录
                LoginUser loginUser = loginUserMapper
                        .selectOne(new LambdaQueryWrapper<LoginUser>()
                                .eq(LoginUser::getUserId, openid));

                if (loginUser == null) {
                    loginUser = createLoginUser(openid, request);
                }

                return loginUser;
        }

        // 5. 上面都不满足则返回null
        return null;
        */
    }

    /**
     * 创建使用微信小程序登录的用户
     * @param openid    微信返回的openid
     * @param request   请求
     * @return  数据库的LoginUser对象
     */
    private LoginUser createLoginUser(String openid, HttpServletRequest request) {
        //获取远程ipf址地
        String remoteHost = request.getRemoteHost();
        LoginUser loginUser = LoginUser.builder()
                .userId(openid)
                .userRegtime(new Date())
                .modifyTime(new Date())
                .userLasttime(new Date())
                .userLastip(remoteHost)
                .userRegip(remoteHost)
                .status(1).build();
        //插入数据库
        loginUserMapper.insert(loginUser);
        return loginUser;
    }
}